/* ====================================== toast  ====================================== */
import React from 'react'
import { Upload } from 'antd'
import { DndProvider, useDrag, useDrop } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'
import { PlusOutlined, LoadingOutlined } from '@ant-design/icons'
import update from 'immutability-helper'
// ===================================================================== 
const { $fn, $Lazy } = window
// ===================================================================== Lazy
const Button 	= $Lazy.load(()=>import('@antd/button'))
const Modal 	= $Lazy.state(()=>import('@antd/modal'))
const message 	= $Lazy.file(()=>import('@antd/message'))
const TableModal = $Lazy.state(()=>import('@antd/common/upload-table'))
// ===================================================================== 

// 获取 base64
const getBase64  = file => {
	return new Promise((resolve, reject) => {
		const reader = new FileReader()
		reader.readAsDataURL(file)
		reader.onload = () => resolve(reader.result)
		reader.onerror = error => reject(error)
	})
}
const getType = f => ({
	img: { bool: f === 'image/jpeg' || f === 'image/png' || f === 'image/jpg' , msg: '图片文件' },
	pdf: { bool: f === 'application/pdf', msg:'PDF 文件'},
	word: { bool: f === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', msg:'word 文件'},
	excel: { bool: f === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || f ==='application/vnd.ms-excel', msg:'Excel 文件'}
})
const getFileList = value => {
	let list = []
	value.forEach((v,i) => {
		if(v){
			list.push({ uid: '-' + (i+1),	name: 'image.png', status: 'done', url: $fn.getImagePrefix(v) })
		}
	})
	return list
}
// 拖动组件
//
const type = 'DragableUploadList'
const DragableUploadListItem = ({ originNode, moveRow, file, fileList }) => {
  const ref = React.useRef();
  const index = fileList.indexOf(file);
  const [{ isOver, dropClassName }, drop] = useDrop({
    accept: type,
    collect: monitor => {
      const { index: dragIndex } = monitor.getItem() || {};
      if (dragIndex === index) {
        return {};
      }
      return {
        isOver: monitor.isOver(),
        dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
      };
    },
    drop: item => {
      moveRow(item.index, index);
    },
  });
  const [, drag] = useDrag({
    type,
    item: { index },
    collect: monitor => ({
      isDragging: monitor.isDragging(),
    }),
  });
  drop(drag(ref));
  return (
    <div
      ref={ref}
      className={`ant-upload-draggable-list-item ${isOver ? dropClassName : ''}`}
      style={{ cursor: 'move' }}
    >
		{originNode}
    </div>
  );
}
const delPrefix = url => {
	url = $fn.hasObject(url) ? url.img_path : url
	const { img_domain } = $fn.getUser() || {}
	return url.replace(img_domain,'')
}
// =====================================================================
// 修改上传文件、报告单、图片的接口地址和参数及返回结果处理 2021-10-9  84,150,159,217,228,331,358,381，427，450行--马婷 api='upload/img'
const Index = ({ className, title, children, fileType='img', mode,isMsg, hand, onQuery, ghost=true, preview=false, imports, api=`${window.globalConfig.uploadUrl}/upload.php`, onChanged, onChange, name, value, param, query, code=126, multiple, btnConfig, disabled, btnText='上传图片', reconfirm, op_key, fileName, covid }, ref)=> {
	const [ loading, setLoading ] = React.useState( false )
	const modalRef = React.useRef()
	// const [ previewTitle, setPreviewTitle ] = React.useState( )
	const [ previewImage, setPreviewImage ] = React.useState( )
	const [ img, setImg ] = React.useState()
	const [ parameter, setParameter ] = React.useState()
	const [fileList, setFileList] = React.useState([]);
	const fileListRef = React.useRef()
	const tableModalRef = React.useRef()
	// 当选择图片时
	const onUpload = React.useCallback(( { file, fileList } )=>{
	    const status = file.status
		if(hand){ return  }
		const txt = imports ? '导入' : '上传'
		
		const type = getType(file.type)
		
		if( fileType === 'img' ){
			if(type.img.bool){
				setFileList(fileList)
			}
		}else{
			setFileList(fileList)
		}
		
	    if( status === 'uploading' ){
	    	setLoading(true)
	    }else if( status === 'done' ){
	    	// message.then(f=>f.success(`${file.name} 文件上传成功!`))
	    	// const imageUrl = file.response.data.path
			const { data, msg, code, status, message:msg1 } = file.response
			if(+code !== 100){
				setLoading(false)
			}
			if(+code === 200 || status === 1 ){
				// message.then(f=>f.success(`${file.name} 文件${txt}成功!`))
				if (reconfirm) {
					tableModalRef.current.refs.ref.open({...data, op_key})
				} else {
					if(isMsg !== false){
						message.then(f=>f.success(`${file.name} 文件${txt}成功!`))
					}
				}
			} else if(+code === 100){		// 导入异步返回code:100时，不提示 2021-9-9 --马婷
				window.onRefresh = () => {
					setLoading(false)
					if (reconfirm) {
						tableModalRef.current.refs.ref.open({...data, op_key})
					}
				}
			} else {		
				if($fn.hasArray(data)){
					let txt = []
					data.forEach((v,i)=>{
						txt.push(<div key={i}>{v}</div>) 
					})
					return message.then(f=>f.error(txt, 300 ))
				}else{
					return message.then(f=>f.error(msg??msg1, 300 ))
				}
			}
			if( ($fn.hasArray(fileType) && fileType.includes('pdf')) ||  fileType === 'img' ){
				if (!multiple) {
					let path = ''
					if ($fn.hasArray(data)) {
						// path = data[0].img_path
						path = data[0].img_path || data[0]
						setImg(path)
					}
					if(!$fn.hasObject(path)&&path.indexOf('http') !== -1){ path = delPrefix(path)  }
					onChanged?.({ model: name ? { [name]:path, name } : path, value: path, data, code })
					onChange?.(path)
				} else {
					setFileList(()=> {
						// const v = $fn.hasArray(data) ? data.map(v => delPrefix(v.img_path)) : []
						const v = $fn.hasArray(data) ? data.map(v => $fn.hasObject(v)?delPrefix(v.file_path):delPrefix(v)) : []
						let f = fileList.filter(v => v.url )
							f = f.map(v => delPrefix(v.url))
						const imgs = [...f, ...v]
						
						onChanged?.({ model: name ? { [name]:imgs, name } : imgs, value:imgs, code})
						onChange?.($fn.hasArray(imgs) ? imgs : null)
						return getFileList(imgs)
					})
					
					// const every = fileList.every( v => v !== undefined || v!=='' )
					// if(every){
					// 	let imgs = fileList.map( v => {
					// 		let path = v.response ? v.response.data[0]['img_path'] : v.url
					// 		if(path.indexOf('http') !== -1){ path = path.replace(img_domain,'') }
					// 		return path
					// 	} )
						
					// 	const every = imgs.every( v => v )
						
					// 	if(every){
					// 		onChanged?.({ model: name ? { [name]:imgs, name } : imgs, value:imgs})
					// 		onChange?.($fn.hasArray(imgs) ? imgs : null)
					// 	}
					// }
				}
			}else if( fileType === 'excel' ){
				const { url } = data
				onChanged?.({ model: name ? { [name]:url } : {}, data, value:url, code})
				onChange?.(url)
			}
	    }else if( status === 'removed' ){
			
		}else if( status === 'error' ){
			message.then(f=>f.error(`${file.name} 文件${txt}失败!`))
	    	setLoading(false)
	    }
	},[onChanged, onChange, name, multiple, hand, imports, isMsg, fileType, op_key, reconfirm])
	
	React.useEffect(()=>{
		if(multiple){
			setFileList( fileList => {
				if(!$fn.hasArray(fileList)){
					fileList = $fn.hasArray(value) ? getFileList(value) : []
				}
				return fileList
			} )
			
		}else{
			if(value) setImg(value)
		}
	},[value, multiple])
	
	const upload = React.useCallback( async ()=>{
		const fd = new FormData()
		setLoading(true)
		fileListRef.current.forEach(file => {
			// fd.append('files[]', file);
			fd.append('file[]', file)
		})
		if(query){
			for(let i in query){
				if(query.hasOwnProperty(i)){
					fd.append(i,query[i])
				}
			}
		}
		fd.set('rename', 1)
		fd.set('app_key', 'norson')
		fd.set('params', 'ZnJvbT1udGRj')
		fd.set('sign', '68c4e2f97684733217348ba32f5b6b36')
		// return window.$http.submit(null,'upload/img',{ param: fd, upload:true, onError:()=> {
		return window.$http.submit(null,`${window.globalConfig.uploadUrl}/upload.php`,{ param: fd, upload:true, onError:()=> {
			message.then(f=>f.error('上传失败'))
			setLoading(false)
		} }).then(data=>{
			setFileList([])
			onChanged?.([])
			setLoading(false)
			return data
		}).catch(() => {
			setLoading(false)
		})
	},[ query, onChanged ])
	
	React.useImperativeHandle( ref, () => ({
		// 自定义上传
		upload,
		getFileList: () => fileListRef.current,
		clear: () => {
			setFileList([])
			onChanged?.([])
		}
	}))
	
	const PlusComponent = () => <>
		{
			loading ? <LoadingOutlined className='f30' /> : <PlusOutlined className='f30'/>
		}
	</>
	
	// 上传图片之前验证
	const beforeUpload = React.useCallback( file =>{
		const type = getType(file.type)
		if(onQuery){
			setParameter(onQuery())
		}
		
		if($fn.hasArray(fileType)){
			let isOk = []
			let msg = ''
			fileType.forEach((v,i)=>{
				msg += (i === fileType.length-1) ? type[v].msg : type[v].msg + '、'
				if(type[v].bool){
					isOk.push(0)
				}
			})
		
			if (isOk.length === 0) {
				message.then(f=>f.warning(`仅允许上传${msg}!`, 3000))
			}else{
				if(hand){
					setFileList( fileList => {
						const list = Array.from(new Set([...fileList, file]))
						fileListRef.current = list
						return list
					} )
					setTimeout(()=> onChanged?.({value:fileListRef.current}), 200)
				}
			}
			if(hand) return false;
			return isOk.length !== 0
		}else{
			if(fileType === 'excel'){
				const isOk = type.excel.bool;
				if (!isOk) {
					message.then(f=>f.warning(`仅允许上传${type.excel.msg}!`, 3000))
				}
				return isOk
			}else if( fileType === 'img'){
				const isOk = type.img.bool;
				if (!isOk) {
					message.then(f=>f.warning(`仅允许上传${type.img.msg}!`, 3000))
				}
				const isLt2M = file.size / 1024 / 1024 < 20;
				if (!isLt2M) {
					message.then(f=>f.warning(`图片必必须小于 20M!`, 3000))
				}
				return isOk && isLt2M
			}else{
				message.then(f=>f.warning(`未允许的上传文件类型`, 3000))
				return false
			}
		}
	},[fileType, hand, onChanged, onQuery])
	
	// 图片预览
	const onPreview = React.useCallback( async file =>{
		if (!file.url && !file.preview) { file.preview = await getBase64(file.originFileObj); }
		modalRef.current.refs.ref.open()
		setPreviewImage(file.url || file.preview)
		// setPreviewTitle(file.name || file.url.substring(file.url.lastIndexOf('/') + 1))
	},[])
	
	let listType = 'picture-card'
	
	if(mode === 'button'){ listType = null }

	const headers = {
		Authorization: covid ? window.$fn.getToken() : 'Bearer ' + window.$fn.getToken(),
		// 导入也需要 Async-Debug 2021-9-8 4:11:43 ?F10: PM? --伍智睿
		'Async-Debug': window.$fn.longSave('async') || 0
	}
	
	let _param = typeof param === 'function' ? param() : param
	let _query = typeof query === 'function' ? query() : query
	// _param = fileType === 'pdf' || (Array.isArray(fileType)&& fileType.includes('pdf')) ? { type:2, modular:126, ..._param } : { modular:code, ..._param }
	if(api === `${window.globalConfig.uploadUrl}/upload.php` ){
		_param = { rename:1,app_key:'norson',params:'ZnJvbT1udGRj',sign:'68c4e2f97684733217348ba32f5b6b36',  ..._param }
	}else{
		 _param = fileType === 'pdf' || (Array.isArray(fileType)&& fileType.includes('pdf')) ? { type:2, modular:126, ..._param } : { modular:code, ..._param }
	}
	// 拖动
	const moveRow = React.useCallback((dragIndex, hoverIndex) => {
			const dragRow = fileList[dragIndex]
			setFileList(fileList => {
				const list = update(fileList, {
					$splice: [
						[dragIndex, 1],
						[hoverIndex, 0, dragRow]
					]
				})
				const imgs = list.map(v => delPrefix(v.url) )
				onChange?.($fn.hasArray(imgs) ? imgs : null)
				return list
			})
		}, [fileList, onChange])
	
	return (
		<>
			{
				multiple ? (
					<DndProvider backend={HTML5Backend}>
						<Upload
							className		= 'rel'
							// name 			= { multiple ? 'files[]' : 'file'}
							name 			= { multiple?(api===`${window.globalConfig.uploadUrl}/upload.php`?'file':'files[]'):'file' }
							// action 			= { window.globalConfig.api + api}
							action 			= { api.indexOf('http') === -1 ? window.globalConfig.api + api : api }
							listType		= { listType }
							showUploadList	= { multiple || hand ? true : false }
							beforeUpload	= { beforeUpload }
							onChange	 	= { hand ? null : onUpload }
							onPreview		= { hand ? null : onPreview }
							headers			= { headers }
							fileList		= { fileList }
							disabled		= { disabled }
							data            = { parameter ? parameter : (_query ? _query : _param) }
							multiple        = { multiple ? multiple : (hand ? true : false) }
							onRemove		= { file => {
								const index = fileList.indexOf(file);
								const list = fileList.slice();
								list.splice(index, 1)
								setFileList(list)
								fileListRef.current = list
								onChanged?.({ value:list })
								
								if(fileType === 'img'){
									// let imgs = list.map( v => (v.response ? v.response.data[0]['img_path'] : v.url) )
									let imgs = list.map( v => (v.response ? (v.response.data[0]['img_path'] ? v.response.data[0]['img_path'] : v.response.data[0]) : v.url) )
									onChange?.($fn.hasArray(imgs) ? imgs : null)
								}
							}}
							itemRender={ multiple ? (originNode, file, currFileList) => (
								<DragableUploadListItem
									originNode	= {originNode }
									file 		= { file }
									fileList 	= { currFileList }
									moveRow		= { moveRow }
								/>
							) : null}
						>
							{
								multiple ? (
									<>
										<PlusComponent />
									</>
								) : (
									<>
										{
											mode === 'button' ? (
												<>
													<Button stop={false} loading={loading} disabled={loading || disabled} ghost={ghost} size={hand ? 'middle' : 'small'} {...btnConfig}>
														<span>{btnText}</span>
													</Button>
													{
														hand && <span className='f12 g9 ml10'>只能上传 jpg、png、pdf、word、excel 文件，且不超过 50M</span>
													}
												</>
											) : (
												<>
													{img ? <img src={$fn.getImagePrefix(img)} alt='avatar' style={{ maxWidth: '100%',display:'inline-block' }} /> : <PlusComponent/>}
													{ loading && <div className='h abs_lt i10 fxmc' style={{width:104,background:'rgba(0,0,0,.3)'}}><LoadingOutlined style={{color:$fn.c0, fontSize:30}} /></div> }
												</>
											)
										}
									</>
								)
							}
						</Upload>
					</DndProvider>
				) : (
					<Upload
						className		= 'rel'
						// name 			= { multiple ? 'files[]' : 'file'}
						name 			= { fileName ? fileName : (multiple?(api===`${window.globalConfig.uploadUrl}/upload.php`?'file':'files[]'):'file') }
						// action 			= { window.globalConfig.api() + api}
						action 			= { api.indexOf('http') === -1 ? window.globalConfig.api + api : api }
						listType		= { listType }
						showUploadList	= { multiple || hand ? true : false }
						beforeUpload	= { beforeUpload }
						onChange	 	= { hand ? null : onUpload }
						onPreview		= { hand ? null : onPreview }
						headers			= { headers }
						fileList		= { fileList }
						disabled		= { disabled }
						data            = { parameter ? parameter : (_query ? _query : _param) }
						multiple        = { multiple ? multiple : (hand ? true : false) }
						onRemove		= { file => {
							const index = fileList.indexOf(file);
							const list = fileList.slice();
							list.splice(index, 1)
							setFileList(list)
							fileListRef.current = list
							onChanged?.({ value:list })
							
							if(fileType === 'img'){
								// let imgs = list.map( v => (v.response ? v.response.data[0]['img_path'] : v.url) )
								let imgs = list.map( v => (v.response ? (v.response.data[0]['img_path']?v.response.data[0]['img_path']:v.response.data[0]) : v.url) )
								onChange?.($fn.hasArray(imgs) ? imgs : null)
							}
						}}
					>
						{
							multiple ? (
								<>
									<PlusComponent />
								</>
							) : (
								<>
									{
										mode === 'button' ? (
											<>
												<Button stop={false} loading={loading} disabled={loading || disabled} ghost={ghost} size={hand ? 'middle' : 'small'} {...btnConfig}>
													<span>{btnText}</span>
												</Button>
												{
													hand && <span className='f12 g9 ml10'>只能上传 jpg、png、pdf、word、excel 文件，且不超过 50M</span>
												}
											</>
										) : (
											<>
												{img ? <img src={$fn.getImagePrefix(img)} alt='avatar' style={{ maxWidth: '100%',display:'inline-block' }} /> : <PlusComponent/>}
												{ loading && <div className='h abs_lt i10 fxmc' style={{width:104,background:'rgba(0,0,0,.3)'}}><LoadingOutlined style={{color:$fn.c0, fontSize:30}} /></div> }
											</>
										)
									}
								</>
							)
						}
					</Upload>
				)
			}
			{
				hand && false && (
					<Button className='ml10' label='开始上传' stop={false} size='middle' disabled={loading || disabled || !$fn.hasArray(fileList)} />
				)
			}
			{
				multiple && (
					<Modal title='图片预览' noFooter ref={modalRef} bodyStyle={{padding:10}}>
						<div className='fxc'>
							<img alt='上传图片' title='上传图片' style={{ maxWidth:'100%' }} src={previewImage} />
						</div>
					</Modal>
				)
			}
			{/* 新增上传多类型文件预览  2022年11月7日17:35:11 敖得卓 */}
			{
				!multiple && mode === 'button' && preview ?
					<a href={img} target="_blank" rel="noreferrer" style={{ maxWidth: '100%',display:'block', marginTop: '20px' }}>
						 {$fn.isAssetTypeAnImage(img) ? <img src={img} style={{ maxWidth: '50%',display:'block'}} alt='avatar'  /> : img}
					</a> : null
			}
			
			<TableModal ref={tableModalRef} />
			
		</>
	)
}
export default Index